/***************************************************************************
 *   Copyright (C) 2007 by saa   *
 *   root@saa   *
 ***************************************************************************/

#include <QMetaType>
#include <QTimerEvent>

#include "mainstream.h"
#include "telnetthread.h"
#include "mainwindow.h"
#include "log.h"
#include "utils.h"
#include "compilemode.h"
#include "database.h"


MainStream::MainStream() : mainWindow(NULL)
{
    startTimer(0);
    connect(&DB, SIGNAL(logDatabaseMessage(const QString&, const LogFlag::LogLevels)), \
            this, SLOT(log(const QString &, const LogFlag::LogLevels)));
}

MainStream::~MainStream()
{
    if(mainWindow)
        delete mainWindow;
}

void MainStream::timerEvent(QTimerEvent * event)
{
    killTimer(event->timerId());
    qRegisterMetaType<LinkList>("LinkList");//TODO think where this is must be done?
    qRegisterMetaType<QList<tracerouteNode> >("QList<tracerouteNode>");
    qRegisterMetaType<LogFlag::LogLevels>("LogFlag::LogLevels");
    init();
}

void MainStream::init()
{
//    QStringList arguments(QCoreApplication::arguments());
    //TODO parse input params
    initGUI();
}

void MainStream::initGUI( )
{
    mainWindow = new MainWindow();
    mainWindow->show();
}

void MainStream::saveLinkList(const LinkList & linkList ) const
{
    emit showLinks(linkList);
}


void MainStream::tracerouteToTargetStarted(const QString & /*routeServer*/, const QString & /*startedTarget*/)
{
    //TODO tracerouteToTargetStarted
}

void MainStream::tracerouteToTargetFinished(const QString & /*routeServer*/, const QString & /*finishedTarget*/)
{
    emit oneTracerouteFinished();
}

void MainStream::telnetClientFinished(QObject * /*sender*/)
{
    emit telnetClientFinished();
}

void MainStream::log(const QString & message, const LogFlag::LogLevels logLevel) const
{
    emit logProgrammeMessage(message, logLevel);
}

void MainStream::start(const QList<RouteServer> & routeServerList, const QStringList & targets)
{
    unsigned int targetPerThreadCount = 1;
    unsigned int remainderTargets = 0;
    if(targets.size() > MAX_CONNECTION_COUNT)
    {
        targetPerThreadCount = targets.size() / MAX_CONNECTION_COUNT;
        remainderTargets = targets.size() % MAX_CONNECTION_COUNT;
    }

    log(QString(tr("Total target count: %1")).arg(targets.size()));
    log(QString(tr("Total server count: %1")).arg(routeServerList.size()));
    log(QString(tr("Max server connection count: %1")).arg(MAX_CONNECTION_COUNT));
    log(QString(tr("Target for one connection count: %1")).arg(targetPerThreadCount));

    //for all servers...
    for (int i = 0; i < routeServerList.size(); ++i) {
        //it is possible start several connetctions for each server
        for(int j = 0; j < qMin(MAX_CONNECTION_COUNT, targets.size()); ++j) {
            TelnetThread * thread(new TelnetThread(this));
            connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
            connect(this, SIGNAL(stop()), thread, SLOT(quit()));
            thread->setTelnetParams(routeServerList.at(i));
            /* divide all targets, add remainder target to last thread */
            int targetForThreadCount(targetPerThreadCount + (j == MAX_CONNECTION_COUNT - 1 ? remainderTargets : 0 ));
            thread->setTargetList(targets.mid( j * targetPerThreadCount, targetForThreadCount));
#ifdef ONE_THREAD
            thread->run();
#else
            thread->start();
#endif
        }
    }
}


void MainStream::stopAllThreads( )
{
    emit stop();
}
